package org.lazy.generate.factory;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.sql.ResultSetMetaData;
import java.util.HashSet;
import java.util.Set;

import org.lazy.generate.bean.GeneratorDao;
import org.lazy.generate.bean.GeneratorDataSource;
import org.lazy.generate.bean.GeneratorEntity;
import org.lazy.generate.bean.GeneratorMapper;
import org.lazy.generate.bean.GeneratorTable;
import org.lazy.generate.common.XmlConstants;
import org.lazy.generate.util.FactoryUtil;

public class DaoFactory extends FileFactory{
	/**
	 * 生成Dao接口
	 */
	public static void buildDao(GeneratorDataSource dataSource,GeneratorEntity entity,GeneratorDao dao,GeneratorTable table,ResultSetMetaData metaData) throws Exception{
		if(XmlConstants.IS_NEED_FALSE.equals(dao.getIsNeed())){
			System.out.println("ignore : "+table.getTableName()+" build Dao");
			return;
		}
		String tableName = table.getTableName();
		String entityName = table.getEntityName();
		String entityClassName = createEntityClassName(entityName, tableName);
		String daoClassName = createDaoClassName(entityClassName, tableName);
		String daoPackage = dao.getTargetPackage();
		String targetPath = dao.getTargetPath();
		String daoFilePath = targetPath+"/"+daoPackage.replace(".", "/");
			PrintWriter pw = null;
			File file = createTargetClass(daoFilePath, daoClassName);
			try {
				pw = new PrintWriter(file);
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
			//package
			pw.println("package "+daoPackage+";\n");
			Set<String> importClasses = needImportToDao(entity,dao, table);
			writeImportClass(pw, importClasses);
			pw.println("");
			//class
			pw.println("public interface "+daoClassName+" {\t");
			writeToDao(pw,dataSource,entity, dao, table, metaData);
			pw.println("}");
			pw.flush();
			pw.close();
			System.out.println("success : "+daoClassName+".java");
		
	}
	/**
	 * 生成Dao接口实现类DaoImpl
	 */
	public static void buildDaoImpl(GeneratorDataSource dataSource,GeneratorMapper mapper,GeneratorEntity entity,GeneratorDao dao,GeneratorTable table,ResultSetMetaData metaData) throws Exception{
		if(XmlConstants.IS_NEED_FALSE.equals(dao.getIsNeed())){
			System.out.println("ignore : "+table.getTableName()+" build DaoImpl");
			return;
		}
		String tableName = table.getTableName();
		String entityName = table.getEntityName();
		String entityClassName = createEntityClassName(entityName, tableName);
		String daoClassName = createDaoClassName(entityClassName, tableName);
		String daoImplClassName = createDaoImplClassName(entityClassName, tableName);
		String targetPath = dao.getTargetPath();
		String daoImplPackage = dao.getTargetPackage()+".impl";
		String daoImplFilePath = targetPath+"/"+daoImplPackage.replace(".", "/");
		PrintWriter pw = null;
		File file = createTargetClass(daoImplFilePath, daoImplClassName);
		try {
			pw = new PrintWriter(file);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		//package
		pw.println("package "+daoImplPackage+";\n");
		Set<String> importClasses = needImportToDaoImpl(entity,dao, table);
		writeImportClass(pw, importClasses);
		pw.println("");
		//class
		pw.println("@Repository(\""+lowerCaseFirstAlphabet(daoClassName)+"\")");
		pw.println("public class "+daoImplClassName+" implements "+daoClassName+" {\t");
		writeToDaoImpl(pw, dataSource,mapper,entity, dao, table, metaData);
		pw.println("}");
		pw.flush();
		pw.close();
		System.out.println("success : "+daoImplClassName+".java");
		
	}
	
	
	/**
	 * 生成DaoExt接口
	 */
	public static void buildDaoExt(GeneratorDataSource dataSource,GeneratorEntity entity,GeneratorDao dao,GeneratorTable table,ResultSetMetaData metaData) throws Exception{
		if(XmlConstants.IS_NEED_FALSE.equals(dao.getIsNeed())){
			System.out.println("ignore : "+table.getTableName()+" build DaoExt");
			return ;
		}
		String tableName = table.getTableName();
		String entityName = table.getEntityName();
		String entityClassName = createEntityClassName(entityName, tableName);
		String daoClassName = createDaoClassName(entityClassName, tableName);
		String daoExtClassName = createDaoExtClassName(entityClassName, tableName);
		String targetPath = dao.getTargetPath();
		String daoExtPackage = dao.getTargetPackage();
		String daoExtFilePath = targetPath+"/"+daoExtPackage.replace(".", "/");
		PrintWriter pw = null;
		if(!isExistJavaFile(daoExtFilePath, daoExtClassName)){
			File file = createTargetClass(daoExtFilePath, daoExtClassName);
			try {
				pw = new PrintWriter(file);
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
			//package
			pw.println("package "+daoExtPackage+";\n");
			pw.println("");
			//class
			pw.println("public interface "+daoExtClassName+" extends "+daoClassName+"{\t");
			
			pw.println("}");
			pw.flush();
			pw.close();
			System.out.println("success : "+daoExtClassName+".java");
		}
		
	}
	/**
	 * 生成DaoExt接口实现类DaoImplExt
	 */
	public static void buildDaoImplExt(GeneratorDataSource dataSource,GeneratorEntity entity,GeneratorDao dao,GeneratorTable table,ResultSetMetaData metaData) throws Exception{
		if(XmlConstants.IS_NEED_FALSE.equals(dao.getIsNeed())){
			System.out.println("ignore : "+table.getTableName()+" build DaoImplExt");
			return;
		}
		String tableName = table.getTableName();
		String entityName = table.getEntityName();
		String entityClassName = createEntityClassName(entityName, tableName);
		String daoImplClassName = createDaoImplClassName(entityClassName, tableName);
		String daoExtClassName = createDaoExtClassName(entityClassName, tableName);
		String daoImplExtClassName = createDaoImplExtClassName(entityClassName, tableName);
		String targetPath = dao.getTargetPath();
		String daoImplExtPackage = dao.getTargetPackage()+".impl";
		String daoImplExtFilePath = targetPath+"/"+daoImplExtPackage.replace(".", "/");
		PrintWriter pw = null;
		if(!isExistJavaFile(daoImplExtFilePath, daoImplExtClassName)){
			File file = createTargetClass(daoImplExtFilePath, daoImplExtClassName);
			try {
				pw = new PrintWriter(file);
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
			//package
			pw.println("package "+daoImplExtPackage+";\n");
			pw.println("import org.springframework.stereotype.Repository;\n");
			pw.println("import "+dao.getTargetPackage()+"."+daoExtClassName+";");
			pw.println("");
			//class
			pw.println("@Repository(\""+lowerCaseFirstAlphabet(daoExtClassName)+"\")");
			pw.println("public class "+daoImplExtClassName+" extends "+daoImplClassName+"  implements  "+daoExtClassName+" {\t");
			
			pw.println("}");
			pw.flush();
			pw.close();
			System.out.println("success : "+daoImplExtClassName+".java");
		}
	}
	
	private static void writeToDao(PrintWriter pw,GeneratorDataSource datasource,GeneratorEntity entity,GeneratorDao dao,GeneratorTable table,ResultSetMetaData metaData) throws Exception{
		String tableName = table.getTableName();
		String entityName = table.getEntityName();
		String dbType = datasource.getDbType();
		String entityClassName = createEntityClassName(entityName, tableName);
		String entityConditionClassName = createEntityConditionClassName(entityClassName, tableName);
		String primaryKey = createFieldName(table.getPrimaryKey());
		String primaryKeyJavaType = FactoryUtil.getPrimaryKeyJaveType(table, metaData, dbType);
		pw.println(t1+"public boolean "+d_method_insert+"("+entityClassName+" "+lowerCaseFirstAlphabet(entityClassName)+");");
		pw.println(t1+"public "+entityClassName+" "+d_method_selectByPrimaryKey+"("+primaryKeyJavaType+" "+primaryKey+");");
		pw.println(t1+"public Long "+d_method_countByCondition+"("+entityConditionClassName+" condition);");
		pw.println(t1+"public List<"+entityClassName+"> "+d_method_selectByCondition+"("+entityConditionClassName+" condition);");
		pw.println(t1+"public boolean "+d_method_updateByPrimaryKey+"("+entityClassName+" "+lowerCaseFirstAlphabet(entityClassName)+");");
		pw.println(t1+"public boolean "+d_method_deleteByPrimaryKey+"("+primaryKeyJavaType+" "+primaryKey+");");
		pw.println(t1+"public boolean "+d_method_deleteBatchByPrimaryKey+"(List<"+primaryKeyJavaType+"> "+primaryKey+"s);");
	}
	private static Set<String> needImportToDao(GeneratorEntity entity,GeneratorDao dao,GeneratorTable table){
		Set<String> set = new HashSet<String>();
		String tableName = table.getTableName();
		String entityName = table.getEntityName();
		String entityClassName = createEntityClassName(entityName, tableName);
		String entityConditionClassName = createEntityConditionClassName(entityName, tableName);
		String entityPackage = entity.getTargetPackage();
		String entityClassNameFull = createFullEntityClassName(entityPackage, entityClassName);
		String entityClassConditionNameFull = createFullEntityClassName(entityPackage, entityConditionClassName);
		set.add("java.util.List");
		set.add(entityClassNameFull);
		set.add(entityClassConditionNameFull);
		return set;
	}
	
	
	private static void writeToDaoImpl(PrintWriter pw,GeneratorDataSource datasource,GeneratorMapper mapper,GeneratorEntity entity,GeneratorDao dao,GeneratorTable table,ResultSetMetaData metaData) throws Exception{
		String tableName = table.getTableName();
		String tablePrimaryKey = table.getPrimaryKey();
		String dbType = datasource.getDbType();
		String entityPrimaryKey = createFieldName(tablePrimaryKey);
		String entityName = table.getEntityName();
		String entityClassName = createEntityClassName(entityName, tableName);
		String mapperXmlName = createMapperXmlName(entityClassName, tableName);
		String mapperXmlPackage = mapper.getTargetPackage();
		String namepace = mapperXmlPackage+"."+mapperXmlName;
		String entityConditionClassName = createEntityConditionClassName(entityName, tableName);
		String primaryKeyJavaType = FactoryUtil.getPrimaryKeyJaveType(table, metaData, dbType);
		pw.println(t1+"@Autowired");
		pw.println(t1+"private SqlSessionFactory sqlSessionFactory;");
		pw.println(t1+"protected SqlSession getSession() {");
		pw.println(t2+"return sqlSessionFactory.openSession();");
		pw.println(t1+"}");
		//insert
		pw.println(t1+"public boolean "+d_method_insert+"("+entityClassName+" "+lowerCaseFirstAlphabet(entityClassName)+") {");
		pw.println(t2+"int flag = getSession().insert(\""+namepace+"."+d_method_insert+"\", "+lowerCaseFirstAlphabet(entityClassName)+");");
		pw.println(t2+"if(flag == 1){");
		pw.println(t3+"return true;");
		pw.println(t2+"}");
		pw.println(t2+"return false;");
		pw.println(t1+"}");
		//selectByPrimaryKey
		pw.println(t1+"public "+entityClassName+" "+d_method_selectByPrimaryKey+"("+primaryKeyJavaType+" "+entityPrimaryKey+") {");
		pw.println(t2+entityClassName+" "+entityClassName.toLowerCase()+" = getSession().selectOne(\""+namepace+"."+d_method_selectByPrimaryKey+"\", "+entityPrimaryKey+");");
		pw.println(t2+"return "+entityClassName.toLowerCase()+";");
		pw.println(t1+"}");
		//countByCondition
		pw.println(t1+"public Long "+d_method_countByCondition+"("+entityConditionClassName+" condition) {");
		pw.println(t2+"Long count = getSession().selectOne(\""+namepace+"."+d_method_countByCondition+"\", condition);");
		pw.println(t2+"return count;");
		pw.println(t1+"}");
		//selectByCondition
		pw.println(t1+"public List<"+entityClassName+"> "+d_method_selectByCondition+"("+entityConditionClassName+" condition) {");
		pw.println(t2+"List<"+entityClassName+"> list = getSession().selectList(\""+namepace+"."+d_method_selectByCondition+"\", condition);");
		pw.println(t2+"return list;");
		pw.println(t1+"}");
		//updateByPrimaryKey
		pw.println(t1+"public boolean "+d_method_updateByPrimaryKey+"("+entityClassName+" "+lowerCaseFirstAlphabet(entityClassName)+") {");
		pw.println(t2+"int flag = getSession().update(\""+namepace+"."+d_method_updateByPrimaryKey+"\", "+lowerCaseFirstAlphabet(entityClassName)+");");
		pw.println(t2+"if(flag == 1){");
		pw.println(t3+"return true;");
		pw.println(t2+"}");
		pw.println(t2+"return false;");
		pw.println(t1+"}");
		//deleteByPrimaryKey
		pw.println(t1+"public boolean "+d_method_deleteByPrimaryKey+"("+primaryKeyJavaType+" "+entityPrimaryKey+") {");
		pw.println(t2+"int flag = getSession().delete(\""+namepace+"."+d_method_deleteByPrimaryKey+"\", "+entityPrimaryKey+");");
		pw.println(t2+"if(flag == 1){");
		pw.println(t3+"return true;");
		pw.println(t2+"}");
		pw.println(t2+"return false;");
		pw.println(t1+"}");
		//deleteBatchByPrimaryKey
		pw.println(t1+"public boolean "+d_method_deleteBatchByPrimaryKey+"(List<"+primaryKeyJavaType+"> primaryKeys) {");
		pw.println(t2+"int flag = getSession().delete(\""+namepace+"."+d_method_deleteBatchByPrimaryKey+"\", primaryKeys);");
		pw.println(t2+"if(flag > 0){");
		pw.println(t3+"return true;");
		pw.println(t2+"}");
		pw.println(t2+"return false;");
		pw.println(t1+"}");

	}
	private static Set<String> needImportToDaoImpl(GeneratorEntity entity,GeneratorDao dao,GeneratorTable table){
		Set<String> set = new HashSet<String>();
		String tableName = table.getTableName();
		String entityName = table.getEntityName();
		String entityClassName = createEntityClassName(entityName, tableName);
		String entityConditionClassName = createEntityConditionClassName(entityName, tableName);
		String entityPackage = entity.getTargetPackage();
		String entityClassNameFull = createFullEntityClassName(entityPackage, entityClassName);
		String entityClassConditionNameFull = createFullEntityClassName(entityPackage, entityConditionClassName);
		String daoPackage = dao.getTargetPackage();
		String daoClassName = createDaoClassName(entityClassName, tableName);
		String daoClassNameFull = createFullDaoClassName(daoPackage, daoClassName);
		set.add("org.apache.ibatis.session.SqlSession");
		set.add("org.apache.ibatis.session.SqlSessionFactory");
		set.add("org.springframework.beans.factory.annotation.Autowired");
		set.add("org.springframework.stereotype.Repository");
		set.add("java.util.List");
		set.add(daoClassNameFull);
		set.add(entityClassNameFull);
		set.add(entityClassConditionNameFull);
		return set;
	}
}
